Setup
n<-nrow(subset_selected)
set.seed(123)
n_s = sample(n,10000)
train = subset_selected[n_s, ]
crossValidationCont = function(df,K,a,nperfmeas=6)
{ set.seed(123)
n = nrow(df)
nhold = round(n/K) # size of holdout set
iperm = sample(n)
perfmeas = matrix(0,K,nperfmeas)
models = vector(mode="list", length=3)
year = vector(mode="list", length=3)
for(k in 1:K)
{ indices = (((k-1)*nhold+1):(k*nhold))
if( k==K ) indices = (((k-1)*nhold+1):n)
indices = iperm[indices]
traine = df[-indices,]
holdoute = df[indices,]
models[[k]] = lm(price~mark_cat+year+mileage_cat+log_vol_engine+fuel+car_type,data=traine)
pred = predict(models[[k]],newdata=holdoute,interval="prediction",level=a)
RSS = c(crossprod(models[[k]]$residuals))
MSE = RSS / length(models[[k]]$residuals)
x = intervalScore(pred, holdoute$price, a)
y= sqrt(MSE)
z = summary(models[[k]])$r.squared
perfmeas[k,1:4] = x$summary
perfmeas[k,5] = y
perfmeas[k,6] = z
year[[k]] = traine$year
}
avgperfmeas = apply(perfmeas,2,mean)
list(perfmeasbyfold=perfmeas, avgperfmeas=avgperfmeas, models= models, year= year)
}
crossValidationCont2 = function(df,K,a,nperfmeas=6)
{ set.seed(123)
n = nrow(df)
nhold = round(n/K) # size of holdout set
iperm = sample(n)
perfmeas = matrix(0,K,nperfmeas)
models = vector(mode="list", length=3)
year = vector(mode="list", length=3)
predi = vector(mode="list", length=3)
pri = vector(mode="list", length=3)
for(k in 1:K)
{ indices = (((k-1)*nhold+1):(k*nhold))
if( k==K ) indices = (((k-1)*nhold+1):n)
indices = iperm[indices]
traine = df[-indices,]
holdoute = df[indices,]
models[[k]] = lm(price~mark_cat+year+mileage_cat+log_vol_engine+fuel+car_type,data=traine, weights = 1/(traine$year)^2)
pred = predict(models[[k]],newdata=holdoute,interval="prediction",level=a, weights = 1/(holdoute$year)^2)
RSS = c(crossprod(models[[k]]$residuals))
MSE = RSS / length(models[[k]]$residuals)
x = intervalScore(pred, holdoute$price, a)
y= sqrt(MSE)
z = summary(models[[k]])$r.squared
perfmeas[k,1:4] = x$summary
perfmeas[k,5] = y
perfmeas[k,6] = z
year[[k]] = traine$year
predi[[k]] = pred
pri[[k]] = holdoute$price
}
avgperfmeas = apply(perfmeas,2,mean)
list(perfmeasbyfold=perfmeas, avgperfmeas=avgperfmeas, models= models, year= year, pred = predi, price = pri)
}
crossValidationCont3 = function(df,K,a,nperfmeas=6)
{ set.seed(123)
n = nrow(df)
nhold = round(n/K) # size of holdout set
iperm = sample(n)
perfmeas = matrix(0,K,nperfmeas)
models = vector(mode="list", length=3)
year = vector(mode="list", length=3)
predi = vector(mode="list", length=3)
pri = vector(mode="list", length=3)
for(k in 1:K)
{ indices = (((k-1)*nhold+1):(k*nhold))
if( k==K ) indices = (((k-1)*nhold+1):n)
indices = iperm[indices]
traine = df[-indices,]
holdoute = df[indices,]
models[[k]] = lm(I(log(price))~mark_cat+year+mileage_cat+log_vol_engine+fuel+car_type,data=traine)
pred1 = predict(models[[k]],newdata=holdoute,interval="prediction",level=a)
pred = exp(pred1)
RSS = c(crossprod(models[[k]]$residuals))
MSE = RSS / length(models[[k]]$residuals)
x = intervalScore(pred, holdoute$price, a)
y= sqrt(MSE)
z = summary(models[[k]])$r.squared
perfmeas[k,1:4] = x$summary
perfmeas[k,5] = y
perfmeas[k,6] = z
year[[k]] = traine$year
predi[[k]] = pred
pri[[k]] = holdoute$price
}
avgperfmeas = apply(perfmeas,2,mean)
list(perfmeasbyfold=perfmeas, avgperfmeas=avgperfmeas, models= models, year= year, pred = predi, price = pri)
}
intervalScore = function(predObj,actual,level) {
n = nrow(predObj)
alpha = 1-level
ilow = (actual<predObj[,2]) # overestimation
ihigh = (actual>predObj[,3]) # underestimation
sumlength = sum(predObj[,3]-predObj[,2]) # sum of lengths of prediction intervals
sumlow = sum(predObj[ilow,2]-actual[ilow])*2/alpha
sumhigh = sum(actual[ihigh]-predObj[ihigh,3])*2/alpha
avglength = sumlength/n
IS = (sumlength+sumlow+sumhigh)/n # average length + average under/over penalties
cover = mean(actual>= predObj[,2] & actual<=predObj[,3])
summ = c(level,avglength,IS,cover)
# summary with level, average length, interval score, coverage rate, r^2, rmse
imiss = which(ilow | ihigh)
list(summary=summ, imiss=imiss)
}
ols_step_best_subset(lm(price~mark_cat+year+mileage_cat+log_vol_engine+fuel+car_type+gdpc,data=train))
Best Subsets Regression
--------------------------------------------------------------------------
Model Index Predictors
--------------------------------------------------------------------------
1 year
2 year car_type
3 year mileage_cat car_type
4 year mileage_cat fuel car_type
5 mark_cat year mileage_cat fuel car_type
6 mark_cat year mileage_cat log_vol_engine fuel car_type
7 mark_cat year mileage_cat log_vol_engine fuel car_type gdpc
--------------------------------------------------------------------------
Subsets Regression Summary
--------------------------------------------------------------------------------------------------------------------------------------------------------------
Adj. Pred
Model R-Square R-Square R-Square C(p) AIC SBIC SBC MSEP FPE HSP APC
--------------------------------------------------------------------------------------------------------------------------------------------------------------
1 0.4331 0.4330 0.4327 11826.1632 213461.9378 185080.4132 213483.5688 1.091154e+12 109137238.4019 10914.8160 0.5672
2 0.6354 0.6352 0.6348 4041.5913 209056.6401 180669.9789 209107.1124 701879354586.3881 70230066.4790 7023.7099 0.3649
3 0.7074 0.7071 0.7067 1268.9664 206864.1012 178470.4096 206950.6253 563184727342.0479 56380481.1251 5638.6131 0.2928
4 0.7245 0.7241 0.7235 614.7308 206269.6787 177872.3313 206377.8338 530418063646.8668 53116154.1273 5312.1482 0.2758
5 0.7337 0.7333 0.7327 261.4335 205934.9011 177533.8372 206064.6872 512698419504.8883 51357128.5591 5136.2286 0.2666
6 0.7407 0.7402 0.7393 -3.6592 205672.8528 177272.1069 205809.8493 499387849825.0785 50028809.8706 5003.3841 0.2597
7 0.7407 0.7402 0.7393 -3.0000 205673.5096 177272.7693 205817.7164 499370749041.4341 50032100.9365 5003.7141 0.2597
--------------------------------------------------------------------------------------------------------------------------------------------------------------
AIC: Akaike Information Criteria
SBIC: Sawa's Bayesian Information Criteria
SBC: Schwarz Bayesian Criteria
MSEP: Estimated error of prediction, assuming multivariate normality
FPE: Final Prediction Error
HSP: Hocking's Sp
APC: Amemiya Prediction Criteria
reg_model= crossValidationCont(train,3,0.5,6)
weighted_model = crossValidationCont2(train,3,0.5,6)
transformed_model = crossValidationCont3(train,3,0.8,6)
d = lm(price~mark_cat+year+mileage_cat+log_vol_engine+fuel+car_type,data=train)
plot(d$fitted.values,d$residuals, ylab="Residuals", xlab = "Fitted Values", main = "OLS Residuals")

plot(train$year,d$residuals, ylab="Residuals", xlab = "Year",main = "Year against OLS Residuals")

de = lm(price~mark_cat+year+mileage_cat+log_vol_engine+fuel+car_type,data=train, weights = 1/(train$year)^2)
plot(de$fitted.values,de$residuals, ylab="Residuals", xlab = "Fitted Values",main = "WLS Residuals")

plot(reg_model$models[[1]]$fitted.values,reg_model$models[[1]]$residuals)

plot(reg_model$models[[2]]$fitted.values,reg_model$models[[2]]$residuals)

plot(reg_model$models[[3]]$fitted.values,reg_model$models[[3]]$residuals)

plot(reg_model$year[[1]],reg_model$models[[1]]$residuals)

plot(reg_model$year[[2]],reg_model$models[[2]]$residuals)

plot(reg_model$year[[3]],reg_model$models[[3]]$residuals)

plot(weighted_model$models[[1]]$fitted.values,weighted_model$models[[1]]$residuals)

plot(weighted_model$models[[2]]$fitted.values,weighted_model$models[[2]]$residuals)

plot(weighted_model$models[[3]]$fitted.values,weighted_model$models[[3]]$residuals)

plot(transformed_model$models[[1]]$fitted.values,transformed_model$models[[1]]$residuals, main = "Fold 1", xlab = "Fitted Values", ylab = "Residuals")

plot(transformed_model$models[[2]]$fitted.values,transformed_model$models[[2]]$residuals, main = "Fold 2", xlab = "Fitted Values", ylab = "Residuals")

plot(transformed_model$models[[3]]$fitted.values,transformed_model$models[[3]]$residuals, main = "Fold 3", xlab = "Fitted Values", ylab = "Residuals")

res1 = transformed_model$price[[1]] - exp(transformed_model$models[[1]]$fitted.values)
longer object length is not a multiple of shorter object length
res2 = transformed_model$price[[2]] - exp(transformed_model$models[[2]]$fitted.values)
longer object length is not a multiple of shorter object length
res3 = transformed_model$price[[3]] - exp(transformed_model$models[[3]]$fitted.values)
longer object length is not a multiple of shorter object length
plot(exp(transformed_model$models[[1]]$fitted.values),res1, main = "Fold 1", xlab = "Fitted Values", ylab = "Residuals")

plot(exp(transformed_model$models[[2]]$fitted.values),res2, main = "Fold 2", xlab = "Fitted Values", ylab = "Residuals")

plot(exp(transformed_model$models[[3]]$fitted.values),res3, main = "Fold 3", xlab = "Fitted Values", ylab = "Residuals")

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQojIFNldHVwCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCmxpYnJhcnkobWxiZW5jaCkKbGlicmFyeShyYW5kb21Gb3Jlc3QpCmxpYnJhcnkocGFydHkpCmxpYnJhcnkocnBhcnQpCmxpYnJhcnkocnBhcnQucGxvdCkKbGlicmFyeShsZWFwcykKbGlicmFyeShvbHNycikKbGlicmFyeShtYWdyaXR0cikKbGlicmFyeSh0aWJibGUpCmBgYAoKYGBge3J9Cm48LW5yb3coc3Vic2V0X3NlbGVjdGVkKQpzZXQuc2VlZCgxMjMpCm5fcyA9IHNhbXBsZShuLDEwMDAwKQp0cmFpbiA9IHN1YnNldF9zZWxlY3RlZFtuX3MsIF0KYGBgCgoKYGBge3J9CmNyb3NzVmFsaWRhdGlvbkNvbnQgPSBmdW5jdGlvbihkZixLLGEsbnBlcmZtZWFzPTYpCnsgc2V0LnNlZWQoMTIzKQogIG4gPSBucm93KGRmKQogIG5ob2xkID0gcm91bmQobi9LKSAjIHNpemUgb2YgaG9sZG91dCBzZXQgCiAgaXBlcm0gPSBzYW1wbGUobikKICBwZXJmbWVhcyA9IG1hdHJpeCgwLEssbnBlcmZtZWFzKSAgCiAgbW9kZWxzID0gdmVjdG9yKG1vZGU9Imxpc3QiLCBsZW5ndGg9MykKICB5ZWFyID0gdmVjdG9yKG1vZGU9Imxpc3QiLCBsZW5ndGg9MykKICBmb3IoayBpbiAxOkspCiAgeyBpbmRpY2VzID0gKCgoay0xKSpuaG9sZCsxKTooaypuaG9sZCkpCiAgICBpZiggaz09SyApIGluZGljZXMgPSAoKChrLTEpKm5ob2xkKzEpOm4pCiAgICBpbmRpY2VzID0gaXBlcm1baW5kaWNlc10KICAgIHRyYWluZSA9IGRmWy1pbmRpY2VzLF0KICAgIGhvbGRvdXRlID0gZGZbaW5kaWNlcyxdCiAgICBtb2RlbHNbW2tdXSA9IGxtKHByaWNlfm1hcmtfY2F0K3llYXIrbWlsZWFnZV9jYXQrbG9nX3ZvbF9lbmdpbmUrZnVlbCtjYXJfdHlwZSxkYXRhPXRyYWluZSkKICAgIHByZWQgPSBwcmVkaWN0KG1vZGVsc1tba11dLG5ld2RhdGE9aG9sZG91dGUsaW50ZXJ2YWw9InByZWRpY3Rpb24iLGxldmVsPWEpCiAgICBSU1MgPSBjKGNyb3NzcHJvZChtb2RlbHNbW2tdXSRyZXNpZHVhbHMpKQogICAgTVNFID0gUlNTIC8gbGVuZ3RoKG1vZGVsc1tba11dJHJlc2lkdWFscykKICAgIHggPSBpbnRlcnZhbFNjb3JlKHByZWQsIGhvbGRvdXRlJHByaWNlLCBhKQogICAgeT0gc3FydChNU0UpCiAgICB6ID0gc3VtbWFyeShtb2RlbHNbW2tdXSkkci5zcXVhcmVkCiAgICBwZXJmbWVhc1trLDE6NF0gPSB4JHN1bW1hcnkKICAgIHBlcmZtZWFzW2ssNV0gPSB5CiAgICBwZXJmbWVhc1trLDZdID0gegogICAgeWVhcltba11dID0gdHJhaW5lJHllYXIKICB9CiAgYXZncGVyZm1lYXMgPSBhcHBseShwZXJmbWVhcywyLG1lYW4pCiAgbGlzdChwZXJmbWVhc2J5Zm9sZD1wZXJmbWVhcywgYXZncGVyZm1lYXM9YXZncGVyZm1lYXMsIG1vZGVscz0gbW9kZWxzLCB5ZWFyPSB5ZWFyKQp9CmBgYAoKYGBge3J9CmNyb3NzVmFsaWRhdGlvbkNvbnQyID0gZnVuY3Rpb24oZGYsSyxhLG5wZXJmbWVhcz02KQp7IHNldC5zZWVkKDEyMykKICBuID0gbnJvdyhkZikKICBuaG9sZCA9IHJvdW5kKG4vSykgIyBzaXplIG9mIGhvbGRvdXQgc2V0IAogIGlwZXJtID0gc2FtcGxlKG4pCiAgcGVyZm1lYXMgPSBtYXRyaXgoMCxLLG5wZXJmbWVhcykgIAogIG1vZGVscyA9IHZlY3Rvcihtb2RlPSJsaXN0IiwgbGVuZ3RoPTMpCiAgeWVhciA9IHZlY3Rvcihtb2RlPSJsaXN0IiwgbGVuZ3RoPTMpCiAgcHJlZGkgPSB2ZWN0b3IobW9kZT0ibGlzdCIsIGxlbmd0aD0zKQogIHByaSA9IHZlY3Rvcihtb2RlPSJsaXN0IiwgbGVuZ3RoPTMpCiAgZm9yKGsgaW4gMTpLKQogIHsgaW5kaWNlcyA9ICgoKGstMSkqbmhvbGQrMSk6KGsqbmhvbGQpKQogICAgaWYoIGs9PUsgKSBpbmRpY2VzID0gKCgoay0xKSpuaG9sZCsxKTpuKQogICAgaW5kaWNlcyA9IGlwZXJtW2luZGljZXNdCiAgICB0cmFpbmUgPSBkZlstaW5kaWNlcyxdCiAgICBob2xkb3V0ZSA9IGRmW2luZGljZXMsXQogICAgbW9kZWxzW1trXV0gPSBsbShwcmljZX5tYXJrX2NhdCt5ZWFyK21pbGVhZ2VfY2F0K2xvZ192b2xfZW5naW5lK2Z1ZWwrY2FyX3R5cGUsZGF0YT10cmFpbmUsIHdlaWdodHMgPSAxLyh0cmFpbmUkeWVhcileMikKICAgIHByZWQgPSBwcmVkaWN0KG1vZGVsc1tba11dLG5ld2RhdGE9aG9sZG91dGUsaW50ZXJ2YWw9InByZWRpY3Rpb24iLGxldmVsPWEsIHdlaWdodHMgPSAxLyhob2xkb3V0ZSR5ZWFyKV4yKQogICAgUlNTID0gYyhjcm9zc3Byb2QobW9kZWxzW1trXV0kcmVzaWR1YWxzKSkKICAgIE1TRSA9IFJTUyAvIGxlbmd0aChtb2RlbHNbW2tdXSRyZXNpZHVhbHMpCiAgICB4ID0gaW50ZXJ2YWxTY29yZShwcmVkLCBob2xkb3V0ZSRwcmljZSwgYSkKICAgIHk9IHNxcnQoTVNFKQogICAgeiA9IHN1bW1hcnkobW9kZWxzW1trXV0pJHIuc3F1YXJlZAogICAgcGVyZm1lYXNbaywxOjRdID0geCRzdW1tYXJ5CiAgICBwZXJmbWVhc1trLDVdID0geQogICAgcGVyZm1lYXNbayw2XSA9IHoKICAgIHllYXJbW2tdXSA9IHRyYWluZSR5ZWFyCiAgICBwcmVkaVtba11dID0gcHJlZAogICAgcHJpW1trXV0gPSBob2xkb3V0ZSRwcmljZQogIH0KICBhdmdwZXJmbWVhcyA9IGFwcGx5KHBlcmZtZWFzLDIsbWVhbikKICBsaXN0KHBlcmZtZWFzYnlmb2xkPXBlcmZtZWFzLCBhdmdwZXJmbWVhcz1hdmdwZXJmbWVhcywgbW9kZWxzPSBtb2RlbHMsIHllYXI9IHllYXIsIHByZWQgPSBwcmVkaSwgcHJpY2UgPSBwcmkpCn0KYGBgCgpgYGB7cn0KY3Jvc3NWYWxpZGF0aW9uQ29udDMgPSBmdW5jdGlvbihkZixLLGEsbnBlcmZtZWFzPTYpCnsgc2V0LnNlZWQoMTIzKQogIG4gPSBucm93KGRmKQogIG5ob2xkID0gcm91bmQobi9LKSAjIHNpemUgb2YgaG9sZG91dCBzZXQgCiAgaXBlcm0gPSBzYW1wbGUobikKICBwZXJmbWVhcyA9IG1hdHJpeCgwLEssbnBlcmZtZWFzKSAgCiAgbW9kZWxzID0gdmVjdG9yKG1vZGU9Imxpc3QiLCBsZW5ndGg9MykKICB5ZWFyID0gdmVjdG9yKG1vZGU9Imxpc3QiLCBsZW5ndGg9MykKICBwcmVkaSA9IHZlY3Rvcihtb2RlPSJsaXN0IiwgbGVuZ3RoPTMpCiAgcHJpID0gdmVjdG9yKG1vZGU9Imxpc3QiLCBsZW5ndGg9MykKICBmb3IoayBpbiAxOkspCiAgeyBpbmRpY2VzID0gKCgoay0xKSpuaG9sZCsxKTooaypuaG9sZCkpCiAgICBpZiggaz09SyApIGluZGljZXMgPSAoKChrLTEpKm5ob2xkKzEpOm4pCiAgICBpbmRpY2VzID0gaXBlcm1baW5kaWNlc10KICAgIHRyYWluZSA9IGRmWy1pbmRpY2VzLF0KICAgIGhvbGRvdXRlID0gZGZbaW5kaWNlcyxdCiAgICBtb2RlbHNbW2tdXSA9IGxtKEkobG9nKHByaWNlKSl+bWFya19jYXQreWVhcittaWxlYWdlX2NhdCtsb2dfdm9sX2VuZ2luZStmdWVsK2Nhcl90eXBlLGRhdGE9dHJhaW5lKQogICAgcHJlZDEgPSBwcmVkaWN0KG1vZGVsc1tba11dLG5ld2RhdGE9aG9sZG91dGUsaW50ZXJ2YWw9InByZWRpY3Rpb24iLGxldmVsPWEpCiAgICBwcmVkID0gZXhwKHByZWQxKQogICAgUlNTID0gYyhjcm9zc3Byb2QobW9kZWxzW1trXV0kcmVzaWR1YWxzKSkKICAgIE1TRSA9IFJTUyAvIGxlbmd0aChtb2RlbHNbW2tdXSRyZXNpZHVhbHMpCiAgICB4ID0gaW50ZXJ2YWxTY29yZShwcmVkLCBob2xkb3V0ZSRwcmljZSwgYSkKICAgIHk9IHNxcnQoTVNFKQogICAgeiA9IHN1bW1hcnkobW9kZWxzW1trXV0pJHIuc3F1YXJlZAogICAgcGVyZm1lYXNbaywxOjRdID0geCRzdW1tYXJ5CiAgICBwZXJmbWVhc1trLDVdID0geQogICAgcGVyZm1lYXNbayw2XSA9IHoKICAgIHllYXJbW2tdXSA9IHRyYWluZSR5ZWFyCiAgICBwcmVkaVtba11dID0gcHJlZAogICAgcHJpW1trXV0gPSBob2xkb3V0ZSRwcmljZQogIH0KICBhdmdwZXJmbWVhcyA9IGFwcGx5KHBlcmZtZWFzLDIsbWVhbikKICBsaXN0KHBlcmZtZWFzYnlmb2xkPXBlcmZtZWFzLCBhdmdwZXJmbWVhcz1hdmdwZXJmbWVhcywgbW9kZWxzPSBtb2RlbHMsIHllYXI9IHllYXIsIHByZWQgPSBwcmVkaSwgcHJpY2UgPSBwcmkpCn0KYGBgCgpgYGB7cn0KaW50ZXJ2YWxTY29yZSA9IGZ1bmN0aW9uKHByZWRPYmosYWN0dWFsLGxldmVsKSB7IApuID0gbnJvdyhwcmVkT2JqKQphbHBoYSA9IDEtbGV2ZWwKaWxvdyA9IChhY3R1YWw8cHJlZE9ialssMl0pICMgb3ZlcmVzdGltYXRpb24KaWhpZ2ggPSAoYWN0dWFsPnByZWRPYmpbLDNdKSAjIHVuZGVyZXN0aW1hdGlvbgpzdW1sZW5ndGggPSBzdW0ocHJlZE9ialssM10tcHJlZE9ialssMl0pICMgc3VtIG9mIGxlbmd0aHMgb2YgcHJlZGljdGlvbiBpbnRlcnZhbHMgCnN1bWxvdyA9IHN1bShwcmVkT2JqW2lsb3csMl0tYWN0dWFsW2lsb3ddKSoyL2FscGhhCnN1bWhpZ2ggPSBzdW0oYWN0dWFsW2loaWdoXS1wcmVkT2JqW2loaWdoLDNdKSoyL2FscGhhCmF2Z2xlbmd0aCA9IHN1bWxlbmd0aC9uCklTID0gKHN1bWxlbmd0aCtzdW1sb3crc3VtaGlnaCkvbiAjIGF2ZXJhZ2UgbGVuZ3RoICsgYXZlcmFnZSB1bmRlci9vdmVyIHBlbmFsdGllcyAKY292ZXIgPSBtZWFuKGFjdHVhbD49IHByZWRPYmpbLDJdICYgYWN0dWFsPD1wcmVkT2JqWywzXSkKc3VtbSA9IGMobGV2ZWwsYXZnbGVuZ3RoLElTLGNvdmVyKQojIHN1bW1hcnkgd2l0aCBsZXZlbCwgYXZlcmFnZSBsZW5ndGgsIGludGVydmFsIHNjb3JlLCBjb3ZlcmFnZSByYXRlLCByXjIsIHJtc2UKaW1pc3MgPSB3aGljaChpbG93IHwgaWhpZ2gpCmxpc3Qoc3VtbWFyeT1zdW1tLCBpbWlzcz1pbWlzcykKfQpvbHNfc3RlcF9iZXN0X3N1YnNldChsbShwcmljZX5tYXJrX2NhdCt5ZWFyK21pbGVhZ2VfY2F0K2xvZ192b2xfZW5naW5lK2Z1ZWwrY2FyX3R5cGUrZ2RwYyxkYXRhPXRyYWluKSkKcmVnX21vZGVsPSBjcm9zc1ZhbGlkYXRpb25Db250KHRyYWluLDMsMC41LDYpCndlaWdodGVkX21vZGVsID0gY3Jvc3NWYWxpZGF0aW9uQ29udDIodHJhaW4sMywwLjUsNikKdHJhbnNmb3JtZWRfbW9kZWwgPSBjcm9zc1ZhbGlkYXRpb25Db250Myh0cmFpbiwzLDAuOCw2KQpgYGAKCmBgYHtyfQpkID0gbG0ocHJpY2V+bWFya19jYXQreWVhcittaWxlYWdlX2NhdCtsb2dfdm9sX2VuZ2luZStmdWVsK2Nhcl90eXBlLGRhdGE9dHJhaW4pCnBsb3QoZCRmaXR0ZWQudmFsdWVzLGQkcmVzaWR1YWxzLCB5bGFiPSJSZXNpZHVhbHMiLCB4bGFiID0gIkZpdHRlZCBWYWx1ZXMiLCBtYWluID0gIk9MUyBSZXNpZHVhbHMiKQpwbG90KHRyYWluJHllYXIsZCRyZXNpZHVhbHMsIHlsYWI9IlJlc2lkdWFscyIsIHhsYWIgPSAiWWVhciIsbWFpbiA9ICJZZWFyIGFnYWluc3QgT0xTIFJlc2lkdWFscyIpCmRlID0gbG0ocHJpY2V+bWFya19jYXQreWVhcittaWxlYWdlX2NhdCtsb2dfdm9sX2VuZ2luZStmdWVsK2Nhcl90eXBlLGRhdGE9dHJhaW4sIHdlaWdodHMgPSAxLyh0cmFpbiR5ZWFyKV4yKQpwbG90KGRlJGZpdHRlZC52YWx1ZXMsZGUkcmVzaWR1YWxzLCB5bGFiPSJSZXNpZHVhbHMiLCB4bGFiID0gIkZpdHRlZCBWYWx1ZXMiLG1haW4gPSAiV0xTIFJlc2lkdWFscyIpCmBgYAoKCmBgYHtyfQpwbG90KHJlZ19tb2RlbCRtb2RlbHNbWzFdXSRmaXR0ZWQudmFsdWVzLHJlZ19tb2RlbCRtb2RlbHNbWzFdXSRyZXNpZHVhbHMpCnBsb3QocmVnX21vZGVsJG1vZGVsc1tbMl1dJGZpdHRlZC52YWx1ZXMscmVnX21vZGVsJG1vZGVsc1tbMl1dJHJlc2lkdWFscykKcGxvdChyZWdfbW9kZWwkbW9kZWxzW1szXV0kZml0dGVkLnZhbHVlcyxyZWdfbW9kZWwkbW9kZWxzW1szXV0kcmVzaWR1YWxzKQpgYGAKCmBgYHtyfQpwbG90KHJlZ19tb2RlbCR5ZWFyW1sxXV0scmVnX21vZGVsJG1vZGVsc1tbMV1dJHJlc2lkdWFscykKcGxvdChyZWdfbW9kZWwkeWVhcltbMl1dLHJlZ19tb2RlbCRtb2RlbHNbWzJdXSRyZXNpZHVhbHMpCnBsb3QocmVnX21vZGVsJHllYXJbWzNdXSxyZWdfbW9kZWwkbW9kZWxzW1szXV0kcmVzaWR1YWxzKQpgYGAKCmBgYHtyfQpwbG90KHdlaWdodGVkX21vZGVsJG1vZGVsc1tbMV1dJGZpdHRlZC52YWx1ZXMsd2VpZ2h0ZWRfbW9kZWwkbW9kZWxzW1sxXV0kcmVzaWR1YWxzKQpwbG90KHdlaWdodGVkX21vZGVsJG1vZGVsc1tbMl1dJGZpdHRlZC52YWx1ZXMsd2VpZ2h0ZWRfbW9kZWwkbW9kZWxzW1syXV0kcmVzaWR1YWxzKQpwbG90KHdlaWdodGVkX21vZGVsJG1vZGVsc1tbM11dJGZpdHRlZC52YWx1ZXMsd2VpZ2h0ZWRfbW9kZWwkbW9kZWxzW1szXV0kcmVzaWR1YWxzKQpgYGAKYGBge3J9CnBsb3QodHJhbnNmb3JtZWRfbW9kZWwkbW9kZWxzW1sxXV0kZml0dGVkLnZhbHVlcyx0cmFuc2Zvcm1lZF9tb2RlbCRtb2RlbHNbWzFdXSRyZXNpZHVhbHMsIG1haW4gPSAiRm9sZCAxIiwgeGxhYiA9ICJGaXR0ZWQgVmFsdWVzIiwgeWxhYiA9ICJSZXNpZHVhbHMiKQpwbG90KHRyYW5zZm9ybWVkX21vZGVsJG1vZGVsc1tbMl1dJGZpdHRlZC52YWx1ZXMsdHJhbnNmb3JtZWRfbW9kZWwkbW9kZWxzW1syXV0kcmVzaWR1YWxzLCBtYWluID0gIkZvbGQgMiIsIHhsYWIgPSAiRml0dGVkIFZhbHVlcyIsIHlsYWIgPSAiUmVzaWR1YWxzIikKcGxvdCh0cmFuc2Zvcm1lZF9tb2RlbCRtb2RlbHNbWzNdXSRmaXR0ZWQudmFsdWVzLHRyYW5zZm9ybWVkX21vZGVsJG1vZGVsc1tbM11dJHJlc2lkdWFscywgbWFpbiA9ICJGb2xkIDMiLCB4bGFiID0gIkZpdHRlZCBWYWx1ZXMiLCB5bGFiID0gIlJlc2lkdWFscyIpCmBgYAoKYGBge3J9CnJlczEgPSB0cmFuc2Zvcm1lZF9tb2RlbCRwcmljZVtbMV1dICAtIGV4cCh0cmFuc2Zvcm1lZF9tb2RlbCRtb2RlbHNbWzFdXSRmaXR0ZWQudmFsdWVzKQpyZXMyID0gdHJhbnNmb3JtZWRfbW9kZWwkcHJpY2VbWzJdXSAgLSBleHAodHJhbnNmb3JtZWRfbW9kZWwkbW9kZWxzW1syXV0kZml0dGVkLnZhbHVlcykKcmVzMyA9IHRyYW5zZm9ybWVkX21vZGVsJHByaWNlW1szXV0gIC0gZXhwKHRyYW5zZm9ybWVkX21vZGVsJG1vZGVsc1tbM11dJGZpdHRlZC52YWx1ZXMpCnBsb3QoZXhwKHRyYW5zZm9ybWVkX21vZGVsJG1vZGVsc1tbMV1dJGZpdHRlZC52YWx1ZXMpLHJlczEsIG1haW4gPSAiRm9sZCAxIiwgeGxhYiA9ICJGaXR0ZWQgVmFsdWVzIiwgeWxhYiA9ICJSZXNpZHVhbHMiKQpwbG90KGV4cCh0cmFuc2Zvcm1lZF9tb2RlbCRtb2RlbHNbWzJdXSRmaXR0ZWQudmFsdWVzKSxyZXMyLCBtYWluID0gIkZvbGQgMiIsIHhsYWIgPSAiRml0dGVkIFZhbHVlcyIsIHlsYWIgPSAiUmVzaWR1YWxzIikKcGxvdChleHAodHJhbnNmb3JtZWRfbW9kZWwkbW9kZWxzW1szXV0kZml0dGVkLnZhbHVlcykscmVzMywgbWFpbiA9ICJGb2xkIDMiLCB4bGFiID0gIkZpdHRlZCBWYWx1ZXMiLCB5bGFiID0gIlJlc2lkdWFscyIpCmBgYA==